using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Log = UnityEngine.Debug;
using Object = UnityEngine.Object;
using System.Net;
using System.Xml.Serialization;

public static class UnityHelper
{
    #region 拼接URL

    public static string URLDIC(string serviceUrl, Dictionary<string, string> queryParams)
    {
        // 创建Web访问对象
        var url = serviceUrl;
        // 添加查询参数
        if (queryParams != null && queryParams.Count > 0)
        {
            var queryString = "";
            foreach (var kvp in queryParams)
            {
                var key = Uri.EscapeDataString(kvp.Key);
                var value = Uri.EscapeDataString(kvp.Value);
                queryString += $"{key}={value}&";
            }

            queryString = queryString.TrimEnd('&');
            url += "?" + queryString;
        }

        return url;
    }

    public static string URLDICINT(string serviceUrl, Dictionary<string, string> queryParams)
    {
        // 创建Web访问对象
        var url = serviceUrl;
        // 添加查询参数
        if (queryParams != null && queryParams.Count > 0)
        {
            var queryString = "";
            foreach (var kvp in queryParams)
            {
                var key = Uri.EscapeDataString(kvp.Key);
                var value = Uri.EscapeDataString(kvp.Value);
                queryString += $"{key}={value}&";
            }

            queryString = queryString.TrimEnd('&');
            url += "?" + queryString;
        }

        return url;
    }

    #endregion


    #region 屏幕飘字

    /// <summary>
    /// 对象池
    /// </summary>
    private static Dictionary<string, List<GameObject>> pool = new Dictionary<string, List<GameObject>>();

    private static GameObject go;
    private static CanvasScaler scaler;

    private static Queue<GameObject> newUI = new Queue<GameObject>();

    static IEnumerator MoveFly(Graphic rt, Color color, float time)
    {
        float speed = (Screen.height / 2 - 100) / time;
        var lerp = Mathf.PingPong(Time.time, time) / time;
        while (rt.rectTransform.localPosition.y < Screen.height / 2 - 100)
        {
            rt.color = Color.Lerp(new Color(rt.color.r, rt.color.g, rt.color.b, rt.color.a),
                new Color(rt.color.r, rt.color.g, rt.color.b, 0), lerp * Time.deltaTime);
            rt.rectTransform.Translate(Vector3.up * speed * Time.deltaTime);
            yield return new WaitForEndOfFrame();
        }

        RecycleObj(rt.gameObject, color);
    }

    public static GameObject GoUI;
    private static bool isSHow;

    public static int BytesLength(this string str)
    {
	    if (str.Length == 0) return 0;

	    ASCIIEncoding ascii = new ASCIIEncoding();

	    int tempLen = 0;

	    byte[] s = ascii.GetBytes(str);

	    for (int i = 0; i < s.Length; i++) {

		    if ((int)s[i] == 63) {

			    tempLen += 2;

		    } else {

			    tempLen += 1;

		    }

	    }

	    return tempLen;
    }

    public static string Intersect(this string str, int len, int pnum = 2)
    {
	    int sl = str.BytesLength();
	    if (len >= sl)
		    return str;

	    ASCIIEncoding ascii = new ASCIIEncoding();

	    int tempLen = pnum;
	    int i = 0;
	    byte[] s = ascii.GetBytes(str);

	    if (tempLen < len)
	    {
		    for (; i < s.Length; i++)
		    {
			    int ttlen;
			    if ((int)s[i] == 63) 
			    {
				    ttlen = tempLen + 2;

			    } else {

				    ttlen = tempLen + 1;
			    }

			    if (ttlen <= len)
				    tempLen = ttlen;
			    else
			    {
				    break;
			    }
		    }
	    }
	    
	    
	    str = str.Substring(0, i);

	    for (int j = 0; j < pnum; j++)
	    {
		    str += ".";
	    }

	    return str;
    }
    

    public static T DeepCopy<T>(T obj)
    {
        object retval;
        using (MemoryStream ms = new MemoryStream())
        {
            XmlSerializer xml = new XmlSerializer(typeof(T));
            xml.Serialize(ms, obj);
            ms.Seek(0, SeekOrigin.Begin);
            retval = xml.Deserialize(ms);
            ms.Close();
        }

        return (T) retval;
    }

    public static void FlyText(string into, Color color, float time = 3.0f, int fontsize = 60)
    {
        InitCanvas();
        scaler.StartCoroutine(MoveFly(GetObj(into, color, fontsize).GetComponent<Text>(), color, time));
    }

    private static void InitCanvas()
    {
        if (go == null)
        {
            go = new GameObject("FlyCanvas", typeof(Canvas));
            Canvas canvas = go.GetComponent<Canvas>();
            scaler = go.AddComponent<CanvasScaler>();
            go.AddComponent<GraphicRaycaster>();
            canvas.renderMode = RenderMode.ScreenSpaceOverlay;
            canvas.sortingOrder = 9999;
            scaler.referencePixelsPerUnit = 100;
            Object.DontDestroyOnLoad(go);
        }
    }


    static IEnumerator MoveFly2(GameObject ui, float time)
    {
        //Text rt = ui.GetComponentInChildren<Text>();
        float speed = (Screen.height / 2 - 100) / time;
        var lerp = Mathf.PingPong(Time.time, time) / time;
        while (ui.transform.localPosition.y < Screen.height / 2 - Screen.height / 4)
        {
            // rt.color = Color.Lerp(new Color(rt.color.r, rt.color.g, rt.color.b, rt.color.a),
            //     new Color(rt.color.r, rt.color.g, rt.color.b, 0), lerp * Time.deltaTime);
            ui.transform.Translate(Vector3.up * speed * Time.deltaTime);
            yield return new WaitForEndOfFrame();
        }

        newUI.Enqueue(ui);
        ui.transform.SetActive(false);
    }

    /// <summary>
    /// 从对象池中获取对象
    /// </summary>
    /// <param name="objName"></param>
    /// <returns></returns>
    private static GameObject GetObj(string info, Color color, int fontsize)
    {
        //结果对象
        GameObject prefab = null;
        //判断是否有该名字的对象池
        if (pool.ContainsKey("CreateText"))
        {
            //对象池里有对象
            if (pool["CreateText"].Count > 0)
            {
                //获取结果
                prefab = pool["CreateText"][0];
                prefab.GetComponent<Text>().text = info;
                //激活对象
                prefab.SetActive(true);
                //从池中移除该对象
                pool["CreateText"].Remove(prefab);
                //返回结果
                return prefab;
            }
        }

        prefab = new GameObject("CreateText", typeof(Text));
        UnityEngine.Object.DontDestroyOnLoad(prefab);
        prefab.transform.SetParent(go.transform);
        prefab.transform.parent.position = new Vector2(0, 150);
        Text text = prefab.GetComponent<Text>();
        text.text = info;
        text.font = Resources.Load<Font>("XueYao");
        if (text.font == null)
            text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
        text.fontSize = fontsize;
        RectTransform rt = prefab.GetComponent<RectTransform>();
        rt.sizeDelta = new Vector2(go.GetComponent<RectTransform>().sizeDelta.x, 100);
        rt.transform.localPosition = new Vector2(0, 0);
        text.verticalOverflow = VerticalWrapMode.Overflow;
        text.alignment = TextAnchor.UpperCenter;
        text.color = color;

        //返回
        return prefab;
    }

    /// <summary>
    /// 回收对象到对象池
    /// </summary>
    /// <param name="objName"></param>
    private static void RecycleObj(GameObject obj, Color color)
    {
        //设置为非激活
        obj.SetActive(false);
        obj.GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
        obj.GetComponent<Text>().color = color;
        //判断是否有该对象的对象池
        if (pool.ContainsKey(obj.name))
        {
            //放置到该对象池
            pool[obj.name].Add(obj);
        }
        else
        {
            //创建该类型的池子，并将对象放入
            pool.Add(obj.name, new List<GameObject>() {obj});
        }
    }

    #endregion

    #region MD5

    public static string GetMD5(FileStream fileStream)
    {
        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
        byte[] hash_byte = md5.ComputeHash(fileStream);
        string str = BitConverter.ToString(hash_byte);
        str = str.Replace("-", "");
        return str;
    }

    #endregion

    #region 下载

    private static Action<float> OnProgress;

    public static CustomAwaiteManager<byte[]> DownLoad(string url, Action<float> progress = null)
    {
        OnProgress = progress;
        var awaiter = new CustomAwaiteManager<byte[]>();
        UnityToolMono mono = Object.FindObjectOfType<UnityToolMono>();
        if (mono == null)
        {
            GameObject goMono = new GameObject("UnityToolMono");
            mono = goMono.AddComponent<UnityToolMono>();
        }

        mono.StartCoroutine(StartDownload(url, awaiter, null));
        return awaiter;
    }

    public static CustomAwaiteManager<byte[]> DownLoadAndSave(string url, string savePath,
        Action<float> progress = null)
    {
        OnProgress = progress;
        var awaiter = new CustomAwaiteManager<byte[]>();
        UnityToolMono mono = Object.FindObjectOfType<UnityToolMono>();
        if (mono == null)
        {
            GameObject goMono = new GameObject("UnityToolMono");
            mono = goMono.AddComponent<UnityToolMono>();
        }

        mono.StartCoroutine(StartDownload(url, awaiter, savePath));
        return awaiter;
    }

    private static IEnumerator StartDownload(string url, CustomAwaiteManager<byte[]> awaiteManager, string savePath)
    {
        UnityWebRequest uwr = UnityWebRequest.Get(url);
        uwr.downloadHandler = new DownloadHandlerBuffer();
        uwr.SendWebRequest();

        while (!uwr.isDone)
        {
            yield return null;
            OnProgress?.Invoke(uwr.downloadProgress);
        }


        if (!string.IsNullOrEmpty(uwr.error))
        {
            awaiteManager.Complete(null, null);

            Log.LogWarning(uwr.error + "    " + "url:" + url);
        }
        else
        {
            if (!string.IsNullOrEmpty(savePath))
            {
                File.WriteAllBytes(savePath, uwr.downloadHandler.data);
            }

            awaiteManager.Complete(uwr.downloadHandler.data, null);
        }
    }

    /// <summary>
    /// 判断url是否有效
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public static bool IsCanConnect(string url)
    {
        HttpWebRequest req = null;
        HttpWebResponse res = null;
        bool CanCn = true;
        try
        {
            req = (HttpWebRequest) WebRequest.Create(url);
            res = (HttpWebResponse) req.GetResponse();
        }
        catch (Exception e)
        {
            CanCn = false; //无法连接
            Log.LogWarning(e);
        }
        finally
        {
            if (res != null)
            {
                res.Close();
            }
        }

        return CanCn;
    }

    #endregion

    #region 拷贝

    public static void CopyFile(string from, string to)
    {
        byte[] bytes = File.ReadAllBytes(from);
        List<byte> listB = new List<byte>(bytes);
        string random = "PED";
        byte[] bs = Encoding.UTF8.GetBytes(random);
        listB.InsertRange(0, bs);
        listB.InsertRange(listB.Count, bs);
        if (!Directory.Exists(Application.dataPath + "/HotFixDllFolder"))
            Directory.CreateDirectory(Application.dataPath + "/HotFixDllFolder");
        File.WriteAllBytes(to, listB.ToArray());
    }

    #endregion

    #region 创建摄像机铺满的Panel

    public static GameObject CreatPanel(this Camera camera, Material material = null, Texture2D tex = null,
        Vector3 offset = new Vector3())
    {
        camera.transform.position += offset;
        var pp = GameObject.CreatePrimitive(PrimitiveType.Plane);
        Object.DestroyImmediate(pp.GetComponent<Collider>());
        pp.transform.SetParent(camera.transform);
        pp.layer = LayerMask.NameToLayer("Player");
        pp.transform.SetAsLastSibling();
        pp.transform.localPosition = new Vector3(0, 0, camera.farClipPlane - 0.01f);
        pp.transform.eulerAngles = new Vector3(90, 0, 180);
        //pp.transform.position += offset;
        var lt = camera.ScreenToWorldPoint(new Vector3(0, 0, camera.farClipPlane));
        var rb = camera.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, camera.farClipPlane));
        var sc = new Vector3(Mathf.Abs(rb.x - lt.x), 1, Mathf.Abs(lt.y - rb.y));
        var ratio = sc.x / sc.y;
        var scratio = (float) Screen.width / Screen.height;
        if (ratio > scratio)
            sc.z = sc.x / scratio;
        else
            sc.x = sc.z * scratio;
        pp.transform.localScale = sc / 10;
        if (material == null)
        {
            if (tex != null)
            {
                pp.GetComponent<MeshRenderer>().material.SetTexture("_EmissionMap", tex);
                pp.GetComponent<MeshRenderer>().material.SetColor("_EmissionColor", new Color(1, 1, 1));
            }
            else
            {
                pp.GetComponent<MeshRenderer>().material.SetColor("_EmissionColor", new Color(0, 1, 0));
            }
        }
        else
            pp.GetComponent<MeshRenderer>().material = material;

        pp.transform.SetParent(null);
        return pp;
    }

    #endregion

    #region 打开文件夹

    public static bool OpenFolder(string itemPath)
    {
        bool result = false;
        if (string.IsNullOrEmpty(itemPath))
        {
            itemPath = "C:/";
        }
#if !UNITY_WEBPLAYER
        itemPath = Path.GetFullPath(itemPath.Replace(@"/", @"\")); // explorer doesn't like front slashes
        if (File.Exists(itemPath))
        {
#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
            Process.Start("explorer.exe", "/select," + itemPath);
#endif
            result = true;
        }
        else if (Directory.Exists(itemPath))
        {
            // NOTE: We use OpenURL() instead of the explorer process so that it opens explorer inside the folder
            UnityEngine.Application.OpenURL(itemPath);
            result = true;
        }

#endif

        return result;
    }

    #endregion

    #region 选择系统文件

    public static string OpenFolder()
    {
        OpenDialogDir ofn2 = new OpenDialogDir();
        ofn2.pszDisplayName = new string(new char[2000]);
        ; // 存放目录路径缓冲区  
        ofn2.lpszTitle = "选择文件件"; // 标题  
        ofn2.ulFlags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;
        IntPtr pidlPtr = LocalDialog.SHBrowseForFolder(ofn2);

        char[] charArray = new char[2000];
        for (int i = 0; i < 2000; i++)
            charArray[i] = '\0';

        LocalDialog.SHGetPathFromIDList(pidlPtr, charArray);
        string fullDirPath = new String(charArray);
        return fullDirPath = fullDirPath.Substring(0, fullDirPath.IndexOf('\0'));
    }

    public static string OpenFile(string type, string type2 = "")
    {
        OpenFileName openFileName = new OpenFileName();
        openFileName.structSize = Marshal.SizeOf(openFileName);
        // openFileName.filter = "(*.mp4;)\0*.mp4";
        //openFileName.filter =string.Format("(*.{0};\0*.{1})",type,type) ;
        openFileName.filter = string.Format("(*{0};)\0*{1}", type, type2);
        openFileName.file = new string(new char[256]);
        openFileName.maxFile = openFileName.file.Length;
        openFileName.fileTitle = new string(new char[64]);
        openFileName.maxFileTitle = openFileName.fileTitle.Length;
        openFileName.initialDir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
        openFileName.title = "打开文件";
        openFileName.flags = 0x00080000 | 0x00001000 | 0x00000800 | 0x00000008;


        char[] charArray = new char[2000];
        for (int i = 0; i < 2000; i++)
            charArray[i] = '\0';
        if (LocalDialog.GetOpenFileName(openFileName))
        {
            return openFileName.file;
        }

        return "";
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    private class OpenFileName
    {
        public int structSize = 0;
        public IntPtr dlgOwner = IntPtr.Zero;
        public IntPtr instance = IntPtr.Zero;
        public String filter = null;

        public String customFilter = null;
        public int maxCustFilter = 0;
        public int filterIndex = 0;
        public String file = null;
        public int maxFile = 0;
        public String fileTitle = null;
        public int maxFileTitle = 0;
        public String initialDir = null;
        public String title = null;
        public int flags = 0;
        public short fileOffset = 0;
        public short fileExtension = 0;
        public String defExt = null;
        public IntPtr custData = IntPtr.Zero;
        public IntPtr hook = IntPtr.Zero;
        public String templateName = null;
        public IntPtr reservedPtr = IntPtr.Zero;
        public int reservedInt = 0;
        public int flagsEx = 0;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    class OpenDialogDir
    {
        public IntPtr hwndOwner = IntPtr.Zero;
        public IntPtr pidlRoot = IntPtr.Zero;
        public String pszDisplayName = null;
        public String lpszTitle = null;
        public UInt32 ulFlags = 0;
        public IntPtr lpfn = IntPtr.Zero;
        public IntPtr lParam = IntPtr.Zero;
        public int iImage = 0;
    }

    private class LocalDialog
    {
        //链接指定系统函数       打开文件对话框
        [DllImport("Comdlg32.dll", SetLastError = true, ThrowOnUnmappableChar = false, CharSet = CharSet.Auto)]
        public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);

        [DllImport("shell32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
        public static extern IntPtr SHBrowseForFolder([In, Out] OpenDialogDir ofn);

        [DllImport("shell32.dll", SetLastError = true, ThrowOnUnmappableChar = true, CharSet = CharSet.Auto)]
        public static extern bool SHGetPathFromIDList([In] IntPtr pidl, [In, Out] char[] fileName);
    }

    #endregion

    #region MiniMap

    /// <summary>
    /// 创建相机模型显示界面
    /// </summary>
    public static Camera CreateMiniMap(RawImage rawImage, Vector3 WordPos, string mask = "")
    {
        Camera yinpingmodel_camera = new GameObject("CreateMiniMap").AddComponent<Camera>();
        yinpingmodel_camera.transform.position = WordPos;
        yinpingmodel_camera.fieldOfView = 51f;
        int with = Mathf.CeilToInt(rawImage.GetComponent<RectTransform>().sizeDelta.x);
        int hight = Mathf.CeilToInt(rawImage.GetComponent<RectTransform>().sizeDelta.y);
        RenderTexture _renderTexture = new RenderTexture(with == 0 ? Screen.width : with,
            hight == 0 ? Screen.height : hight, 24, RenderTextureFormat.RGB565)
        {
            antiAliasing = 1,
            filterMode = FilterMode.Bilinear,
            anisoLevel = 0,
            useMipMap = false
        };
        yinpingmodel_camera.targetTexture = _renderTexture;
        rawImage.texture = yinpingmodel_camera.targetTexture;
        if (!string.IsNullOrEmpty(mask))
            yinpingmodel_camera.cullingMask = LayerMask.GetMask(mask);
        return yinpingmodel_camera;
    }

    #endregion

    #region 判断是否在某个UI区域内

    public static bool RectContainsScreenPoint(Vector3 point, Canvas canvas, RectTransform rect, Camera camera)
    {
        if (canvas.renderMode != RenderMode.ScreenSpaceOverlay)
        {
            return RectTransformUtility.RectangleContainsScreenPoint(rect, point, camera);
        }

        return GetSpaceRect(canvas, rect, camera).Contains(point);
    }

    private static Rect GetSpaceRect(Canvas canvas, RectTransform rect, Camera camera)
    {
        Rect spaceRect = rect.rect;
        Vector3 spacePos = GetSpacePos(rect, canvas, camera);
        //lossyScale
        spaceRect.x = spaceRect.x * rect.lossyScale.x + spacePos.x;
        spaceRect.y = spaceRect.y * rect.lossyScale.y + spacePos.y;
        spaceRect.width = spaceRect.width * rect.lossyScale.x;
        spaceRect.height = spaceRect.height * rect.lossyScale.y;
        return spaceRect;
    }

    private static Vector3 GetSpacePos(RectTransform rect, Canvas canvas, Camera camera)
    {
        
        if (canvas.renderMode == RenderMode.ScreenSpaceOverlay)
        {
            return rect.position;
        }

        return camera.WorldToScreenPoint(rect.position);
    }

    #endregion

    #region 得到上一级目录

    public static string GetParentPath(string path)
    {
        Directory.SetCurrentDirectory(Directory.GetParent(path).FullName);

        return Directory.GetCurrentDirectory();
    }

    #endregion

    #region 窗口最小化

    [DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll")]
    static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);

    const int SW_SHOWMINIMIZED = 2; //{最小化, 激活}
    const int SW_SHOWMAXIMIZED = 3; //最大化
    const int SW_SHOWRESTORE = 1; //还原

    public static void ShowWindow(int cmd = 2)
    {
        ShowWindow(GetForegroundWindow(), cmd);
    }

    #endregion

    #region 加载图片

    public static IEnumerator SetImageSprite(Image imgSprite, string url, string path = null)
    {
        byte[] results = null;
        //local local
        if (path != null)
        {
            string[] arrStr = url.Split('/');
            string filePath = string.Format("{0}/{1}_{2}", path, arrStr[arrStr.Length - 2], arrStr[arrStr.Length - 1]);

            FileInfo t = new FileInfo(filePath);
            if (t.Exists)
            {
                FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                BinaryReader br = new BinaryReader(fs, Encoding.UTF8);
                int count = br.ReadInt32();
                results = br.ReadBytes(count);
                if (results != null)
                {
                    Rect tempRect = imgSprite.GetComponent<RectTransform>().rect;
                    Texture2D texture =
                        new Texture2D(Mathf.CeilToInt(tempRect.width), Mathf.CeilToInt(tempRect.height));
                    texture.LoadImage(results);
                    yield return null;
                    Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height),
                        new Vector2(0.5f, 0.5f));
                    yield return null;
                    imgSprite.sprite = sprite;
                }

                br.Dispose();
                br.Close();
                fs.Close();

                yield break;
            }
        }

        //down load
        UnityWebRequest webRequest = UnityWebRequest.Get(url);
        yield return webRequest.SendWebRequest();
        if (!string.IsNullOrEmpty(webRequest.error))
        {
            Log.Log("图片加载错误:" + webRequest.error + "," + webRequest.url);
            yield break;
        }

        if (webRequest.isDone && webRequest.error == null)
        {
            results = webRequest.downloadHandler.data;

            //save local
            if (path != null)
            {
                string[] arrStr = url.Split('/');
                string filePath = string.Format("{0}/{1}_{2}", path, arrStr[arrStr.Length - 2],
                    arrStr[arrStr.Length - 1]);

                int count = results.Length;
                FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write);
                using (BinaryWriter bw = new BinaryWriter(fs))
                {
                    bw.Write(count);
                    bw.Write(results);

                    bw.Dispose();
                    bw.Close();
                    fs.Close();
                }
            }

            Rect tempRect = imgSprite.GetComponent<RectTransform>().rect;
            Texture2D texture = new Texture2D(Mathf.CeilToInt(tempRect.width), Mathf.CeilToInt(tempRect.height));
            texture.LoadImage(results);
            yield return null;
            Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height),
                new Vector2(0.5f, 0.5f));
            yield return null;
            imgSprite.sprite = sprite;
        }
    }

    public static IEnumerator SetImagesSprite(List<Image> imgSprites, string url, string path = null)
    {
        byte[] results = null;
        //local local
        if (path != null)
        {
            string[] arrStr = url.Split('/');
            string filePath = string.Format("{0}/{1}_{2}", path, arrStr[arrStr.Length - 2], arrStr[arrStr.Length - 1]);

            FileInfo t = new FileInfo(filePath);
            if (t.Exists)
            {
                FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                BinaryReader br = new BinaryReader(fs, Encoding.UTF8);
                int count = br.ReadInt32();
                results = br.ReadBytes(count);
                if (results != null)
                {
                    for (int i = 0; i < imgSprites.Count; i++)
                    {
                        Rect tempRect = imgSprites[i].GetComponent<RectTransform>().rect;
                        Texture2D texture = new Texture2D(Mathf.CeilToInt(tempRect.width),
                            Mathf.CeilToInt(tempRect.height));
                        texture.LoadImage(results);
                        yield return null;
                        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height),
                            new Vector2(0.5f, 0.5f));
                        yield return null;
                        imgSprites[i].sprite = sprite;
                    }
                }

                br.Dispose();
                br.Close();
                fs.Close();

                yield break;
            }
        }

        //down load
        UnityWebRequest webRequest = UnityWebRequest.Get(url);
        yield return webRequest.SendWebRequest();
        if (!string.IsNullOrEmpty(webRequest.error))
        {
            Log.Log("图片加载错误:" + webRequest.error + "," + webRequest.url);
            yield break;
        }

        if (webRequest.isDone && webRequest.error == null)
        {
            results = webRequest.downloadHandler.data;
            //save local
            if (path != null)
            {
                string[] arrStr = url.Split('/');
                string filePath = string.Format("{0}/{1}_{2}", path, arrStr[arrStr.Length - 2],
                    arrStr[arrStr.Length - 1]);
                int count = results.Length;
                FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write);
                using (BinaryWriter bw = new BinaryWriter(fs))
                {
                    bw.Write(count);
                    bw.Write(results);

                    bw.Dispose();
                    bw.Close();
                    fs.Close();
                }
            }

            for (int i = 0; i < imgSprites.Count; i++)
            {
                if (imgSprites[i] == null) continue;
                Rect tempRect = imgSprites[i].GetComponent<RectTransform>().rect;
                Texture2D texture = new Texture2D(Mathf.CeilToInt(tempRect.width), Mathf.CeilToInt(tempRect.height));
                texture.LoadImage(results);
                yield return null;
                Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height),
                    new Vector2(0.5f, 0.5f));
                yield return null;
                imgSprites[i].sprite = sprite;
            }
        }
    }

    #endregion


    #region Unity列表Content操作

    /// <summary>
    /// 清空列表
    /// </summary>
    /// <param name="content"></param>
    public static void ClearViewContent(this Transform content,bool isSaveFirst=false)
    {
        int lastCount = isSaveFirst ? 1 : 0;
        int childCount = content.childCount;
        for (int i = childCount - 1; i >= lastCount; i--)
            GameObject.DestroyImmediate(content.GetChild(i).gameObject);
    }

    /// <summary>
    /// 通过设定行数初始化列表的高度
    /// </summary>
    /// <param name="contentRect"></param>
    /// <param name="row"></param>
    public static void SetContentHeight(this RectTransform contentRect, int row)
    {
        GridLayoutGroup gridLayoutGroup = contentRect.GetComponent<GridLayoutGroup>();
        float height = row * (gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y) + gridLayoutGroup.padding.top;
        contentRect.sizeDelta = new Vector2(contentRect.sizeDelta.x, height);
    }

    public static void SetContentHeight(this Transform content, int row)
    {
        RectTransform contentRect = content.GetComponent<RectTransform>();
        GridLayoutGroup gridLayoutGroup = content.GetComponent<GridLayoutGroup>();
        float height = row * (gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y) + gridLayoutGroup.padding.top;
        contentRect.sizeDelta = new Vector2(contentRect.sizeDelta.x, height);
    }

    /// <summary>
    /// 通过设定列数初始化列表的宽度
    /// </summary>
    /// <param name="contentRect"></param>
    /// <param name="row"></param>
    public static void SetContentWidth(this RectTransform contentRect, int lie)
    {
        GridLayoutGroup gridLayoutGroup = contentRect.GetComponent<GridLayoutGroup>();
        float width = lie * (gridLayoutGroup.cellSize.x + gridLayoutGroup.spacing.x) + gridLayoutGroup.padding.left;
        contentRect.sizeDelta = new Vector2(width, contentRect.sizeDelta.y);
    }

    public static void SetContentWidth(this Transform content, int lie)
    {
        RectTransform contentRect = content.GetComponent<RectTransform>();
        GridLayoutGroup gridLayoutGroup = content.GetComponent<GridLayoutGroup>();
        float width = lie * (gridLayoutGroup.cellSize.x + gridLayoutGroup.spacing.x) + gridLayoutGroup.padding.left;
        contentRect.sizeDelta = new Vector2(width, contentRect.sizeDelta.y);
    }


    private static void GetRectsList(List<RectTransform> rectTransList, Transform parentTrans, Transform rectChild)
    {
        rectTransList.Add(rectChild.GetComponent<RectTransform>());
        if (rectChild.parent != parentTrans)
            GetRectsList(rectTransList, parentTrans, rectChild.parent);
    }

    #endregion

    #region RawImage自动裁剪图片

    public static Vector2 PicTexture(Texture texture2D, int width, int height)
    {
        Vector2 v = default;
        var pic_width = texture2D.width;
        var pic_height = texture2D.height;

        float lv = 1.0f;
        if (pic_width > width || pic_height > height)
            lv = Mathf.Min((float) height / pic_height, (float) width / pic_width);
        else if (pic_width < width && pic_height < height)
            lv = Mathf.Min((float) width / pic_width, (float) height / pic_height);
        v = new Vector2(pic_width * lv, pic_height * lv);
        return v;
    }

	#endregion

	#region 每次调用函数都会产生低重复概率的随机字符串
	public static string GetRandomString()
	{
		string str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		char[] chastr = str.ToCharArray();
		string num = "";
		System.Random random = new System.Random();
		for (int i = 0; i < 32; i++)
		{
			num += chastr[random.Next(0, chastr.Length)].ToString();
		}
		return num;
	}
	#endregion

}

public class UnityToolMono : MonoBehaviour
{
}

/// <summary>
/// await 下载的工具类
/// </summary>
/// <typeparam name="T"></typeparam>
public class CustomAwaiteManager<T> : INotifyCompletion
{
    public CustomAwaiteManager<T> GetAwaiter()
    {
        return this;
    }

    bool _isDone;

    Action _continuation;
    T _result;

    public bool IsCompleted
    {
        get { return _isDone; }
    }

    public T GetResult()
    {
        return _result;
    }

    public void Complete(T result, Exception e)
    {
        _isDone = true;

        _result = result;
        if (_continuation != null)
        {
            _continuation();
        }
    }

    void INotifyCompletion.OnCompleted(Action continuation)
    {
        _continuation = continuation;
    }
}